<?php namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Models\BrotherCommunity;
use App\Models\Reply;
use App\Models\Resource;
use App\Models\Tag;
use App\Models\UserDcoinsLog;
use App\Models\UserVipFreeOpeCountLog;
use Illuminate\Pagination\Paginator;
use Phphub\Core\CreatorListener;
use App\Models\Topic;
use App\Models\SiteStatus;
use App\Models\Link;
use App\Models\Notification;
use App\Models\Append;
use App\Models\Category;
use App\Models\Banner;
use App\Models\ActiveUser;
use App\Models\HotTopic;
use APP\Models\User;
use Phphub\Handler\Exception\ImageUploadException;
use Phphub\Markdown\Markdown;
use Illuminate\Http\Request;
use App\Http\Requests\StoreTopicRequest;
use Auth;
use Flash;
use Image;
use DB;
use Request as UserRequest;
use Phphub\Notification\Mention;
use App\Activities\UserPublishedNewTopic;
use App\Activities\BlogHasNewArticle;
use App\Activities\UserAddedAppend;
use Carbon\Carbon;
use DfaFilter\SensitiveHelper;

class TopicsController extends Controller implements CreatorListener
{
    public function __construct()
    {
        $this->middleware('auth', ['except' => ['index', 'show']]);
    }

    public function index(Request $request, Topic $topic)
    {
        //DB::enableQueryLog();
        $topics = $topic->getTopicsWithFilter($request->get('filter', 'index'));
        //return response()->json(DB::getQueryLog());

        $links = Link::allFromCache();
        $communities = BrotherCommunity::allFromCache();
        //$banners = Banner::allByPosition();

        $active_users = ActiveUser::fetchAll();
        $hot_topics = HotTopic::fetchAll();

        return view(
            'topics.index',
            compact('topics', 'links', 'banners', 'communities', 'active_users', 'hot_topics')
        );
    }

    public function create(Request $request)
    {
        $categoryId = $request->input('category_id');
//        $categorySelectFlag = true;
//        if ($categoryId == config('phphub.resources_id')) {
//            $categorySelectFlag = false;
//        }
        $category = Category::find($categoryId);
        $categories = Category::where('id', '!=', config('phphub.blog_category_id'))
            ->where('id', '!=', config('phphub.hunt_category_id'))
            ->where('id', '!=', config('phphub.homework_help_id'))
            ->where('id', '!=', config('phphub.algorithm_sources_id'))
            ->where('id', '!=', config('phphub.resources_id'))
            ->where('status', 'yes')
            ->get();

        $tags = Tag::all();

        //
        if (!\Auth::check()) {
            return redirect(route('auth.login'));
        }

        $user = \Auth::user();
        if ($request->input('category_id') == config('phphub.homework_help_id')) {
            $dcoins = UserDcoinsLog::getLatestUDcoinLog($user->id);
            $vipFreeCountLog = UserVipFreeOpeCountLog::getLatestLog($user->id);

            if ((empty($dcoins) || $dcoins->remain_dcoins < 5)
                && (empty($vipFreeCountLog) || $vipFreeCountLog->free_home_help_remain_count == 0)) {
                return response()->view('errors.402');
            }
        }

        $vw = 'topics.create_edit';
        if ($categoryId == config('phphub.resources_id')) {
            $vw = 'topics.create_edit_resources';
        } elseif ($categoryId == config('phphub.algorithm_sources_id')) {
            $vw = 'topics.create_edit_sources';
        } elseif ($categoryId == config('phphub.translate_id')) {
            $vw = 'share_links.create_edit';
        }
        elseif ($categoryId == config('phphub.hunt_category_id'))
        {
            $vw = 'share_links.create_edit';
        }
        return view($vw, compact('categories', 'category', 'tags', 'categorySelectFlag'));
    }


    public function store(StoreTopicRequest $request)
    {
        $data = $request->except('_token');
        // 敏感词检测
        $legal = $this->checkBannedWords($data);
        if (!$legal) {
            return $this->creatorFailed('内容不合适，请不要包含色情、暴力、非法、政治及辱骂等关键词。');
        }

        return app('Phphub\Creators\TopicCreator')->create($this, $data);
    }

    public function show($id, Request $request, $fromCode = false)
    {

        $topic = Topic::where('id', $id)->with('user', 'lastReplyUser', 'tags', 'resource', 'category', 'translateSections')->firstOrFail();


        $category = $topic->category;

        if ($topic->read_right == 1 && !Auth::check())
        {
            return redirect()->route('login-required');
            //$topic->body = '<blockquote><p>该贴被设置了在登录后可阅览...</p></blockquote>';
        }

        if ($topic->isArticle() && $topic->is_draft == 'yes')
        {
            $this->authorize('show_draft', $topic);
        }

        // URL 矫正
        $slug = $request->route('slug');
        if (!empty($topic->slug) && $topic->slug != $slug && !$fromCode)
        {
            return redirect($topic->link(), 301);
        }

        if ($topic->user->is_banned == 'yes') {
            // 未登录，或者已登录但是没有管理员权限
            if (!Auth::check() || (Auth::check() && !Auth::user()->may('manage_topics'))) {
                Flash::error('你访问的文章已被屏蔽，有疑问请发邮件：allenzhang1007@163.com');
                return redirect(route('topics.index'));
            }
            Flash::error('当前文章的作者已被屏蔽，游客与用户将看不到此文章。');
        }

        if (config('phphub.admin_board_cid')
            && $topic->id == config('phphub.admin_board_cid')
            && (!Auth::check() || !Auth::user()->can('access_board'))
        ) {
            Flash::error('您没有权限访问该文章，有疑问请发邮件：810454300@qq.com');
            return redirect()->route('topics.index');
        }

        $replies = $topic->getRepliesWithLimit(config('phphub.replies_perpage'), $request->order_by);

//        //登录后才能阅览
//        if ($topic->read_right == 1 && !Auth::check()) {
//            $replies = $topic->getRepliesWithLimit(config('phphub.replies_perpage'), $request->order_by, 1);
//        }

        $categoryTopics = $topic->getSameCategoryTopics();

        $votedUsers = $topic->votes()->orderBy('id', 'desc')->with('user')->get()->pluck('user');
        $revisionHistory = $topic->revisionHistory()->orderBy('created_at', 'DESC')->first();

        if (!is_self_refresh($request)) {
            $topic->increment('view_count', 1);
            $topic->updated_at = Carbon::now()->toDateTimeString();
            $topic->save();
        }

        //$banners = Banner::allByPosition();

        $cover = $topic->cover();
        if ($topic->isArticle()) {
            if (UserRequest::is('topics*')) {
                return redirect()->to($topic->link());
            }
            $user = $topic->user;

            if (!is_self_refresh($request)) {
                $user->increment('view_count', 1);
            }

            $articleArchieve = $topic->getArticleArchieve($user->id);

            $blog = $topic->blogs()->first();
            $userTopics = $blog->topics()
                ->withoutDraft()
                ->onlyArticle()
                ->orderBy('vote_count', 'desc')
                ->limit(5)
                ->get();

            return view('articles.show', compact(
                'blog',
                'user',
                'topic',
                'replies',
                'categoryTopics',
                'category',
                'banners',
                'cover',
                'votedUsers',
                'userTopics',
                'revisionHistory',
                'articleArchieve'
            ));
        }
        else
        {
            if (!$topic->isTranslate() || $topic->isTranslated())
            {
                $userTopics = $topic->byWhom($topic->user_id)
                    ->withoutDraft()
                    ->withoutBoardTopics()
                    ->recent()
                    ->limit(3)
                    ->get();

                return view('topics.show', compact(
                    'topic',
                    'replies',
                    'categoryTopics',
                    'category',
                    'banners',
                    'cover',
                    'votedUsers',
                    'userTopics',
                    'revisionHistory'
                ));
            } else {
                //翻译详情页的显示

                return view('translate.show', compact(
                    'topic',
                    'replies',
                    'categoryTopics',
                    'category',
                    'banners',
                    'cover',
                    'votedUsers',
                    'userTopics',
                    'revisionHistory'
                ));
            }

        }
    }

    public function edit($id)
    {
        $topic = Topic::with('tags', 'resource')->findOrFail($id);
        $this->authorize('update', $topic);
        $categories = Category::where('id', '!=', config('phphub.blog_category_id'))->get();
        $category = $topic->category;
        $tags = Tag::all();
        $topicTags = array_column($topic->relationsToArray()['tags'], 'name');

        $categoryId = $category->id;
//        $categorySelectFlag = true;
//        if ($categoryId == config('phphub.resources_id') || $categoryId == config('phphub.algorithm_sources_id')) {
//            $categorySelectFlag = false;
//        }
        $topic->body = $topic->body_original;

        if (!$category) {
            return redirect()->back();
        }
        //
        $vw = 'topics.create_edit';
        if ($categoryId == config('phphub.resources_id'))
        {
            $vw = 'topics.create_edit_resources';
        }
        elseif ($categoryId == config('phphub.algorithm_sources_id'))
        {
            $vw = 'topics.create_edit_sources';
        }

        return view($vw, compact('topic', 'categories', 'category', 'tags', 'topicTags'));
    }

    public function append($id, Request $request)
    {
        $topic = Topic::findOrFail($id);
        $this->authorize('append', $topic);

        $markdown = new Markdown;
        $content = $markdown->convertMarkdownToHtml($request->input('content'));

        $append = Append::create(['topic_id' => $topic->id, 'content' => $content]);

        app('Phphub\Notification\Notifier')->newAppendNotify(Auth::user(), $topic, $append);
        app(UserAddedAppend::class)->generate(Auth::user(), $topic, $append);

        return response([
            'status' => 200,
            'message' => lang('Operation succeeded.'),
            'append' => $append
        ]);
    }

    public function update($id, StoreTopicRequest $request, Mention $mentionParser)
    {
        $topic = Topic::findOrFail($id);
        $this->authorize('update', $topic);

        $data = $request->only(
            'title',
            'body',
            'parent_category_id',
            'category_id',
            'link',
            'tags',
            'resource_id',
            'resource_point',
            'resource_dcoin',
            'resource_cost_type',
            'resource_type',
            'resource_category',
            'algorithm_lang'
        );

        // 敏感词检测
        $legal = $this->checkBannedWords($data);
        if (!$legal) {
            return $this->creatorFailed('内容不合适，请不要包含色情、暴力、非法、政治及辱骂等关键词。');
        }

        $data['body'] = $mentionParser->parse($data['body']);

        $markdown = new Markdown;
        $data['body_original'] = $data['body'];
        $data['body'] = $markdown->convertMarkdownToHtml($data['body']);
        $data['excerpt'] = Topic::makeExcerpt($data['body']);

        if ($topic->isArticle() && $request->subject == 'publish' && $topic->is_draft == 'yes') {
            $data['is_draft'] = 'no';
            $data['created_at'] = Carbon::now()->toDateTimeString();

            // Topic Published
            app('Phphub\Notification\Notifier')->newTopicNotify(Auth::user(), $mentionParser, $topic);

            // User activity
            app(UserPublishedNewTopic::class)->generate(Auth::user(), $topic);
            app(BlogHasNewArticle::class)->generate(Auth::user(), $topic, $topic->blogs()->first());

            Auth::user()->decrement('draft_count', 1);
            Auth::user()->increment('article_count', 1);
            $topic->blogs()->first()->increment('article_count', 1);

        }

        if ($topic->isShareLink()) {
            $topic->share_link->link = $data['link'];
            $topic->share_link->site = domain_from_url($data['link']);
            $topic->share_link->save();
        }

        if (empty($data['tags'])) {
            $topic->untag();
        } else {
            $topic->retag($data['tags']);
        }

        // 建立资源话题与资源的关联
        // 12.7 日添加建立源码资源话题与资源的关联
        if ($data['category_id'] == config('phphub.resources_id')
            || $data['parent_category_id'] == config('phphub.resources_id')
        ) {
            if ($topic->resource->id != $data['resource_id']) {
                $resource = Resource::query()->find($data['resource_id']);
                if (!$resource) {
                    return $this->creatorFailed('发布资源失败,请选择并上传资源!');
                }
                $topic->resource->delete();
                $resource->topic_id = $topic->id;
                $resource->cost = $data['resource_point'];
                $resource->cost_type = 1;//积分
                $resource->type = $data['resource_type'] ?? 0;
                $resource->category = $data['resource_category'] ?? 0;
                $resource->save();
            } else {
                $topic->resource->cost = $data['resource_point'];
                $topic->resource->cost_type = 1;//积分
                $topic->resource->type = $data['resource_type'];
                $topic->resource->category = $data['resource_category'];
                $topic->resource->save();
            }
        } else if ($data['category_id'] == config('phphub.algorithm_sources_id')
            || $data['parent_category_id'] == config('phphub.algorithm_sources_id')
        ) {
            if ($topic->resource->id != $data['resource_id']) {
                $resource = Resource::query()->find($data['resource_id']);
                if (!$resource) {
                    return $this->creatorFailed('发布资源失败,请选择并上传资源!');
                }
                $topic->resource->delete();
                $resource->topic_id = $topic->id;
                $resource->cost = $data['resource_dcoin'];
                $resource->cost_type = 2;//D币
                $resource->algorithm_lang = $data['algorithm_lang'] ?? 0;
                $resource->save();
            } else {
                $topic->resource->cost = $data['resource_dcoin'];
                $topic->resource->cost_type = 2;//D币
                $topic->resource->algorithm_lang = $data['algorithm_lang'] ?? 0;
                $topic->resource->save();
            }
        }

        $topic->update($data);

        Flash::success(lang('Operation succeeded.'));

        $topic->collectImages();

        return redirect()->to($topic->link());
    }

    /**
     * ----------------------------------------
     * User Topic Vote function
     * ----------------------------------------
     */

    public function upvote($id)
    {
        $topic = Topic::find($id);
        $topic = app('Phphub\Vote\Voter')->topicUpVote($topic);

        return response(['status' => 200, 'count' => $topic->vote_count]);
    }

    public function downvote($id)
    {
        $topic = Topic::find($id);
        app('Phphub\Vote\Voter')->topicDownVote($topic);

        return response(['status' => 200]);
    }

    /**
     * ----------------------------------------
     * Admin Topic Management
     * ----------------------------------------
     */

    public function recommend($id)
    {
        $topic = Topic::findOrFail($id);
        $this->authorize('recommend', $topic);
        $topic->is_excellent = $topic->is_excellent == 'yes' ? 'no' : 'yes';
        $topic->save();
        Notification::notify('topic_mark_excellent', Auth::user(), $topic->user, $topic);

        return response(['status' => 200, 'message' => lang('Operation succeeded.')]);
    }

    public function pin($id)
    {
        $topic = Topic::findOrFail($id);
        $this->authorize('pin', $topic);

        $topic->order = $topic->order > 0 ? 0 : 999;
        $topic->save();

        return response(['status' => 200, 'message' => lang('Operation succeeded.')]);
    }

    public function sink($id)
    {
        $topic = Topic::findOrFail($id);
        $this->authorize('sink', $topic);

        $topic->order = $topic->order >= 0 ? -1 : 0;
        $topic->save();

        app(UserPublishedNewTopic::class)->remove(Auth::user(), $topic);
        app(BlogHasNewArticle::class)->remove(Auth::user(), $topic, $topic->user->blogs()->first());

        return response(['status' => 200, 'message' => lang('Operation succeeded.')]);
    }

    public function setReadRight($id)
    {
        $topic = Topic::findOrFail($id);
        $this->authorize('setReadRight', $topic);

        $topic->read_right = $topic->read_right == 0 ? 1 : 0;
        $topic->save();

        return response(['status' => 200, 'message' => lang('Operation succeeded.')]);
    }

    public function destroy($id)
    {
        /** @var Topic $topic */
        $topic = Topic::findOrFail($id);
        $this->authorize('delete', $topic);
        DB::transaction(function () use ($topic) {
            $topic->delete();
            Flash::success(lang('Operation succeeded.'));

            $blog = $topic->blogs()->first();

            if ($topic->isArticle() && $topic->is_draft == 'yes') {
                $topic->user()->decrement('draft_count', 1);
            } elseif ($topic->isArticle()) {
                $topic->user()->decrement('article_count', 1);
                $blog->decrement('article_count', 1);
            } else {
                if (!empty($resource = $topic->resource()->first())) {
                    $resource->delete();
                }
                $topic->user()->decrement('topic_count', 1);
            }
            app(UserPublishedNewTopic::class)->remove($topic->user, $topic);
            app(BlogHasNewArticle::class)->remove($topic->user, $topic, $blog);
        });
        return redirect()->route('topics.index');
    }

    /*
     * 结帖
     */
    public function knotHomework(Request $request)
    {

        $topic_id = $request->input('topic_id');

        $flag = $request->input('flag');//1:满意结帖，0:不满意结帖
        if ($flag == 1) {
            $user_ids = $request->input('user_ids');
            $replies_ids = $request->input('replies_ids');
            if (empty($user_ids) || empty($replies_ids) || count($user_ids) <= 0 || count($replies_ids) <= 0) {
                return ['msg' => '您选择的满意结帖，参数错误', 'status' => -1];
            }
        }
        $topic = Topic::where('id', $topic_id)->first();

        if (empty($topic)) {
            return ['msg' => '该话题不存在', 'status' => -1];
        }
        if ($topic->status != 0) {
            return ['msg' => '该话题已结帖，不能重复结帖', 'status' => -1];
        }

        try {
            DB::transaction(function () use ($topic, $flag, $request) {

                $topic->status = ($flag == 1 ? 2 : 1);
                $topic->save();
                if ($flag == 1) {
                    $user_ids = $request->input('user_ids');
                    $replies_ids = $request->input('replies_ids');
                    $user_ids = array_unique($user_ids);
                    $replies_ids = array_unique($replies_ids);
                    $reply_list = Reply::whereIn('id', $replies_ids)->get();

                    foreach ($reply_list as $idx => $reply) {
                        $reply->satisfied_status = 1;
                        $reply->save();
                    }
                    $user_arr = [];

                    $from_user = $topic->user;

                    foreach ($user_ids as $idx => $user_id) {
                        if ($user_id == $from_user->id) {
                            continue;
                        }
                        $dcoin_statistic = UserDcoinsLog::dcoinStatistic($user_id);
                        $dcoin_transfer = 2;//作业帮一个用户，2个D币
                        $userDcoinsLog = new UserDcoinsLog();
                        $userDcoinsLog->user_id = $user_id;
                        $userDcoinsLog->type = 1;//增加
                        $userDcoinsLog->dcoins = $dcoin_transfer;
                        $userDcoinsLog->remain_dcoins = $dcoin_statistic['remain_dcoins'] + $dcoin_transfer;
                        $userDcoinsLog->reason_type = UserDcoinsLog::REASON_TYPE_HOMEWORK_ADD;//作业帮增加
                        $userDcoinsLog->save();
                        $toUser = User::where('id', $user_id)->first();
                        array_push($user_arr, $toUser);

                    }
                    //消耗D币,通知用户
                    app('Phphub\Notification\Notifier')->newHomeworkNotify('homework_add_dcoins', $from_user, $user_arr, $topic);
                }

            });

            return ['msg' => '结帖成功', 'status' => 1];
        } catch (\Illuminate\Database\QueryException $ex) {
            return ['msg' => '结帖失败', 'status' => -1];
        }

    }

    public function uploadImage(Request $request)
    {
        if ($file = $request->file('file')) {
            try {
                $upload_status = app('Phphub\Handler\ImageUploadHandler')->uploadImage($file);
            } catch (ImageUploadException $exception) {
                return ['error' => $exception->getMessage()];
            }
            $data['filename'] = $upload_status['filename'];

            SiteStatus::newImage();
        } else {
            $data['error'] = 'Error while uploading file';
        }
        return $data;
    }

    /**
     * 检测敏感词
     *
     * @param $data
     * @return bool|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
     * @throws \DfaFilter\Exceptions\PdsBusinessException
     * @throws \DfaFilter\Exceptions\PdsSystemException
     */
    public function checkBannedWords($data)
    {
        return true;
        $wordFilePath = resource_path(config('phphub.banned_words_file'));
        // 将标题、正文、标签连接起来检测，提高检测速度
        $checkText = $data['title'] . $data['body'];
        if (isset($data['tags'])) {
            $checkText .= implode('', $data['tags']);
        }
        $handle = SensitiveHelper::init()->setTreeByFile($wordFilePath);
        // 检查内容是否包含敏感词
        if ($handle->islegal($checkText)) {
            return false;
        }
        return true;
    }


    /**
     * ----------------------------------------
     * CreatorListener Delegate
     * ----------------------------------------
     */

    public function creatorFailed($error)
    {
        Flash::error('发布失败：' . $error);
        return redirect('/');
    }

    public function creatorSucceed($topic)
    {
        Flash::success(lang('Operation succeeded.'));
        return redirect()->to($topic->link());
    }
}
